
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

#include <linux/mod_devicetable.h>
#include <linux/of_device.h>

#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/spi/spi.h>


#define  CMD   100
#define	 DATA  101

static int major;
static struct class *dac_class;
static struct gpio_desc *dac_cs;
static unsigned char dac_data = 0;

static struct spi_device *dac_dev;


static int dac_open(struct inode *node, struct file *file)
{
	printk("%s %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}



static int dac_close(struct inode *node, struct file *file)
{
	printk("%s %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}



static ssize_t dac_write(struct file *file, const char __user *buff, size_t size, loff_t *offset)
{
	
	unsigned short ker_buff;
	unsigned char data[2];
	if (size != 2)
		return -EINVAL;
	copy_from_user(&ker_buff, buff, 2);
	ker_buff &= 0xffc;
	data[0] = ker_buff >> 8;
	data[1] = ker_buff;
	//gpiod_set_value(dac_cs, 1);
	
	spi_write(dac_dev, data, 2);
	gpiod_set_value(dac_cs, 0);
	udelay(50);
	return 2;	
}





static struct file_operations dac_ops = {
	.owner  = THIS_MODULE,
	.open    = dac_open,
	.release = dac_close,
	.write = dac_write,
};




static struct of_device_id of_match_table_dac[] = {
	{ .compatible = "dac,zmq", },
	{ },
};


static int dac_probe(struct spi_device *spi)
{
	
	printk("%s %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	dac_dev = spi;

	major = register_chrdev(0, "zmq_dac_chrdev", &dac_ops);
	dac_class = class_create(THIS_MODULE, "dac_class_name");
	if(IS_ERR(dac_class))
	{
		unregister_chrdev(major, "zmq_dac_chrdev");
		return PTR_ERR(dac_class);
	}
	device_create(dac_class, NULL, MKDEV(major, 0), NULL, "dac_zmq");
	dac_cs = gpiod_get_index(&spi->master->dev, "cs", 1, GPIOD_OUT_LOW);

	return 0;
	
}

static int dac_remove(struct spi_device *spi)
{

	device_destroy(dac_class, MKDEV(major, 0));
	class_destroy(dac_class);
	unregister_chrdev(major, "zmq_dac_chrdev");
	gpiod_put(dac_cs);
	return 0;
}


static struct spi_driver dac_drv = {
	.probe = dac_probe,
	.remove = dac_remove,
	.driver = 	{
		.name = "dac",
		.of_match_table = of_match_table_dac,
	},

};



static int dac_init(void)
{
	printk("%s %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	spi_register_driver(&dac_drv);
	
	return 0;
}


static void dac_exit(void)
{
	printk("%s %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);

	spi_unregister_driver(&dac_drv);
}


module_init(dac_init);
module_exit(dac_exit);
MODULE_LICENSE("GPL");






